/*
 * MinIO Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2016 MinIO, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as crypto from "crypto";
import * as errors from "./errors.mjs";
import { getScope, isNumber, isObject, isString, makeDateLong, makeDateShort, uriEscape } from "./internal/helper.mjs";
const signV4Algorithm = 'AWS4-HMAC-SHA256';

// getCanonicalRequest generate a canonical request of style.
//
// canonicalRequest =
//  <HTTPMethod>\n
//  <CanonicalURI>\n
//  <CanonicalQueryString>\n
//  <CanonicalHeaders>\n
//  <SignedHeaders>\n
//  <HashedPayload>
//
function getCanonicalRequest(method, path, headers, signedHeaders, hashedPayload) {
  if (!isString(method)) {
    throw new TypeError('method should be of type "string"');
  }
  if (!isString(path)) {
    throw new TypeError('path should be of type "string"');
  }
  if (!isObject(headers)) {
    throw new TypeError('headers should be of type "object"');
  }
  if (!Array.isArray(signedHeaders)) {
    throw new TypeError('signedHeaders should be of type "array"');
  }
  if (!isString(hashedPayload)) {
    throw new TypeError('hashedPayload should be of type "string"');
  }
  const headersArray = signedHeaders.reduce((acc, i) => {
    // Trim spaces from the value (required by V4 spec)
    const val = `${headers[i]}`.replace(/ +/g, ' ');
    acc.push(`${i.toLowerCase()}:${val}`);
    return acc;
  }, []);
  const requestResource = path.split('?')[0];
  let requestQuery = path.split('?')[1];
  if (!requestQuery) {
    requestQuery = '';
  }
  if (requestQuery) {
    requestQuery = requestQuery.split('&').sort().map(element => !element.includes('=') ? element + '=' : element).join('&');
  }
  return [method.toUpperCase(), requestResource, requestQuery, headersArray.join('\n') + '\n', signedHeaders.join(';').toLowerCase(), hashedPayload].join('\n');
}

// generate a credential string
function getCredential(accessKey, region, requestDate, serviceName = 's3') {
  if (!isString(accessKey)) {
    throw new TypeError('accessKey should be of type "string"');
  }
  if (!isString(region)) {
    throw new TypeError('region should be of type "string"');
  }
  if (!isObject(requestDate)) {
    throw new TypeError('requestDate should be of type "object"');
  }
  return `${accessKey}/${getScope(region, requestDate, serviceName)}`;
}

// Returns signed headers array - alphabetically sorted
function getSignedHeaders(headers) {
  if (!isObject(headers)) {
    throw new TypeError('request should be of type "object"');
  }
  // Excerpts from @lsegal - https://github.com/aws/aws-sdk-js/issues/659#issuecomment-120477258
  //
  //  User-Agent:
  //
  //      This is ignored from signing because signing this causes problems with generating pre-signed URLs
  //      (that are executed by other agents) or when customers pass requests through proxies, which may
  //      modify the user-agent.
  //
  //  Content-Length:
  //
  //      This is ignored from signing because generating a pre-signed URL should not provide a content-length
  //      constraint, specifically when vending a S3 pre-signed PUT URL. The corollary to this is that when
  //      sending regular requests (non-pre-signed), the signature contains a checksum of the body, which
  //      implicitly validates the payload length (since changing the number of bytes would change the checksum)
  //      and therefore this header is not valuable in the signature.
  //
  //  Content-Type:
  //
  //      Signing this header causes quite a number of problems in browser environments, where browsers
  //      like to modify and normalize the content-type header in different ways. There is more information
  //      on this in https://github.com/aws/aws-sdk-js/issues/244. Avoiding this field simplifies logic
  //      and reduces the possibility of future bugs
  //
  //  Authorization:
  //
  //      Is skipped for obvious reasons

  const ignoredHeaders = ['authorization', 'content-length', 'content-type', 'user-agent'];
  return Object.keys(headers).filter(header => !ignoredHeaders.includes(header)).sort();
}

// returns the key used for calculating signature
function getSigningKey(date, region, secretKey, serviceName = 's3') {
  if (!isObject(date)) {
    throw new TypeError('date should be of type "object"');
  }
  if (!isString(region)) {
    throw new TypeError('region should be of type "string"');
  }
  if (!isString(secretKey)) {
    throw new TypeError('secretKey should be of type "string"');
  }
  const dateLine = makeDateShort(date);
  const hmac1 = crypto.createHmac('sha256', 'AWS4' + secretKey).update(dateLine).digest(),
    hmac2 = crypto.createHmac('sha256', hmac1).update(region).digest(),
    hmac3 = crypto.createHmac('sha256', hmac2).update(serviceName).digest();
  return crypto.createHmac('sha256', hmac3).update('aws4_request').digest();
}

// returns the string that needs to be signed
function getStringToSign(canonicalRequest, requestDate, region, serviceName = 's3') {
  if (!isString(canonicalRequest)) {
    throw new TypeError('canonicalRequest should be of type "string"');
  }
  if (!isObject(requestDate)) {
    throw new TypeError('requestDate should be of type "object"');
  }
  if (!isString(region)) {
    throw new TypeError('region should be of type "string"');
  }
  const hash = crypto.createHash('sha256').update(canonicalRequest).digest('hex');
  const scope = getScope(region, requestDate, serviceName);
  const stringToSign = [signV4Algorithm, makeDateLong(requestDate), scope, hash];
  return stringToSign.join('\n');
}

// calculate the signature of the POST policy
export function postPresignSignatureV4(region, date, secretKey, policyBase64) {
  if (!isString(region)) {
    throw new TypeError('region should be of type "string"');
  }
  if (!isObject(date)) {
    throw new TypeError('date should be of type "object"');
  }
  if (!isString(secretKey)) {
    throw new TypeError('secretKey should be of type "string"');
  }
  if (!isString(policyBase64)) {
    throw new TypeError('policyBase64 should be of type "string"');
  }
  const signingKey = getSigningKey(date, region, secretKey);
  return crypto.createHmac('sha256', signingKey).update(policyBase64).digest('hex').toLowerCase();
}

// Returns the authorization header
export function signV4(request, accessKey, secretKey, region, requestDate, sha256sum, serviceName = 's3') {
  if (!isObject(request)) {
    throw new TypeError('request should be of type "object"');
  }
  if (!isString(accessKey)) {
    throw new TypeError('accessKey should be of type "string"');
  }
  if (!isString(secretKey)) {
    throw new TypeError('secretKey should be of type "string"');
  }
  if (!isString(region)) {
    throw new TypeError('region should be of type "string"');
  }
  if (!accessKey) {
    throw new errors.AccessKeyRequiredError('accessKey is required for signing');
  }
  if (!secretKey) {
    throw new errors.SecretKeyRequiredError('secretKey is required for signing');
  }
  const signedHeaders = getSignedHeaders(request.headers);
  const canonicalRequest = getCanonicalRequest(request.method, request.path, request.headers, signedHeaders, sha256sum);
  const serviceIdentifier = serviceName || 's3';
  const stringToSign = getStringToSign(canonicalRequest, requestDate, region, serviceIdentifier);
  const signingKey = getSigningKey(requestDate, region, secretKey, serviceIdentifier);
  const credential = getCredential(accessKey, region, requestDate, serviceIdentifier);
  const signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex').toLowerCase();
  return `${signV4Algorithm} Credential=${credential}, SignedHeaders=${signedHeaders.join(';').toLowerCase()}, Signature=${signature}`;
}
export function signV4ByServiceName(request, accessKey, secretKey, region, requestDate, contentSha256, serviceName = 's3') {
  return signV4(request, accessKey, secretKey, region, requestDate, contentSha256, serviceName);
}

// returns a presigned URL string
export function presignSignatureV4(request, accessKey, secretKey, sessionToken, region, requestDate, expires) {
  if (!isObject(request)) {
    throw new TypeError('request should be of type "object"');
  }
  if (!isString(accessKey)) {
    throw new TypeError('accessKey should be of type "string"');
  }
  if (!isString(secretKey)) {
    throw new TypeError('secretKey should be of type "string"');
  }
  if (!isString(region)) {
    throw new TypeError('region should be of type "string"');
  }
  if (!accessKey) {
    throw new errors.AccessKeyRequiredError('accessKey is required for presigning');
  }
  if (!secretKey) {
    throw new errors.SecretKeyRequiredError('secretKey is required for presigning');
  }
  if (!isNumber(expires)) {
    throw new TypeError('expires should be of type "number"');
  }
  if (expires < 1) {
    throw new errors.ExpiresParamError('expires param cannot be less than 1 seconds');
  }
  if (expires > 604800) {
    throw new errors.ExpiresParamError('expires param cannot be greater than 7 days');
  }
  const iso8601Date = makeDateLong(requestDate);
  const signedHeaders = getSignedHeaders(request.headers);
  const credential = getCredential(accessKey, region, requestDate);
  const hashedPayload = 'UNSIGNED-PAYLOAD';
  const requestQuery = [];
  requestQuery.push(`X-Amz-Algorithm=${signV4Algorithm}`);
  requestQuery.push(`X-Amz-Credential=${uriEscape(credential)}`);
  requestQuery.push(`X-Amz-Date=${iso8601Date}`);
  requestQuery.push(`X-Amz-Expires=${expires}`);
  requestQuery.push(`X-Amz-SignedHeaders=${uriEscape(signedHeaders.join(';').toLowerCase())}`);
  if (sessionToken) {
    requestQuery.push(`X-Amz-Security-Token=${uriEscape(sessionToken)}`);
  }
  const resource = request.path.split('?')[0];
  let query = request.path.split('?')[1];
  if (query) {
    query = query + '&' + requestQuery.join('&');
  } else {
    query = requestQuery.join('&');
  }
  const path = resource + '?' + query;
  const canonicalRequest = getCanonicalRequest(request.method, path, request.headers, signedHeaders, hashedPayload);
  const stringToSign = getStringToSign(canonicalRequest, requestDate, region);
  const signingKey = getSigningKey(requestDate, region, secretKey);
  const signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex').toLowerCase();
  return request.protocol + '//' + request.headers.host + path + `&X-Amz-Signature=${signature}`;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjcnlwdG8iLCJlcnJvcnMiLCJnZXRTY29wZSIsImlzTnVtYmVyIiwiaXNPYmplY3QiLCJpc1N0cmluZyIsIm1ha2VEYXRlTG9uZyIsIm1ha2VEYXRlU2hvcnQiLCJ1cmlFc2NhcGUiLCJzaWduVjRBbGdvcml0aG0iLCJnZXRDYW5vbmljYWxSZXF1ZXN0IiwibWV0aG9kIiwicGF0aCIsImhlYWRlcnMiLCJzaWduZWRIZWFkZXJzIiwiaGFzaGVkUGF5bG9hZCIsIlR5cGVFcnJvciIsIkFycmF5IiwiaXNBcnJheSIsImhlYWRlcnNBcnJheSIsInJlZHVjZSIsImFjYyIsImkiLCJ2YWwiLCJyZXBsYWNlIiwicHVzaCIsInRvTG93ZXJDYXNlIiwicmVxdWVzdFJlc291cmNlIiwic3BsaXQiLCJyZXF1ZXN0UXVlcnkiLCJzb3J0IiwibWFwIiwiZWxlbWVudCIsImluY2x1ZGVzIiwiam9pbiIsInRvVXBwZXJDYXNlIiwiZ2V0Q3JlZGVudGlhbCIsImFjY2Vzc0tleSIsInJlZ2lvbiIsInJlcXVlc3REYXRlIiwic2VydmljZU5hbWUiLCJnZXRTaWduZWRIZWFkZXJzIiwiaWdub3JlZEhlYWRlcnMiLCJPYmplY3QiLCJrZXlzIiwiZmlsdGVyIiwiaGVhZGVyIiwiZ2V0U2lnbmluZ0tleSIsImRhdGUiLCJzZWNyZXRLZXkiLCJkYXRlTGluZSIsImhtYWMxIiwiY3JlYXRlSG1hYyIsInVwZGF0ZSIsImRpZ2VzdCIsImhtYWMyIiwiaG1hYzMiLCJnZXRTdHJpbmdUb1NpZ24iLCJjYW5vbmljYWxSZXF1ZXN0IiwiaGFzaCIsImNyZWF0ZUhhc2giLCJzY29wZSIsInN0cmluZ1RvU2lnbiIsInBvc3RQcmVzaWduU2lnbmF0dXJlVjQiLCJwb2xpY3lCYXNlNjQiLCJzaWduaW5nS2V5Iiwic2lnblY0IiwicmVxdWVzdCIsInNoYTI1NnN1bSIsIkFjY2Vzc0tleVJlcXVpcmVkRXJyb3IiLCJTZWNyZXRLZXlSZXF1aXJlZEVycm9yIiwic2VydmljZUlkZW50aWZpZXIiLCJjcmVkZW50aWFsIiwic2lnbmF0dXJlIiwic2lnblY0QnlTZXJ2aWNlTmFtZSIsImNvbnRlbnRTaGEyNTYiLCJwcmVzaWduU2lnbmF0dXJlVjQiLCJzZXNzaW9uVG9rZW4iLCJleHBpcmVzIiwiRXhwaXJlc1BhcmFtRXJyb3IiLCJpc284NjAxRGF0ZSIsInJlc291cmNlIiwicXVlcnkiLCJwcm90b2NvbCIsImhvc3QiXSwic291cmNlcyI6WyJzaWduaW5nLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBNaW5JTyBKYXZhc2NyaXB0IExpYnJhcnkgZm9yIEFtYXpvbiBTMyBDb21wYXRpYmxlIENsb3VkIFN0b3JhZ2UsIChDKSAyMDE2IE1pbklPLCBJbmMuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdub2RlOmNyeXB0bydcblxuaW1wb3J0ICogYXMgZXJyb3JzIGZyb20gJy4vZXJyb3JzLnRzJ1xuaW1wb3J0IHsgZ2V0U2NvcGUsIGlzTnVtYmVyLCBpc09iamVjdCwgaXNTdHJpbmcsIG1ha2VEYXRlTG9uZywgbWFrZURhdGVTaG9ydCwgdXJpRXNjYXBlIH0gZnJvbSAnLi9pbnRlcm5hbC9oZWxwZXIudHMnXG5pbXBvcnQgdHlwZSB7IElDYW5vbmljYWxSZXF1ZXN0LCBJUmVxdWVzdCwgUmVxdWVzdEhlYWRlcnMgfSBmcm9tICcuL2ludGVybmFsL3R5cGUudHMnXG5cbmNvbnN0IHNpZ25WNEFsZ29yaXRobSA9ICdBV1M0LUhNQUMtU0hBMjU2J1xuXG4vLyBnZXRDYW5vbmljYWxSZXF1ZXN0IGdlbmVyYXRlIGEgY2Fub25pY2FsIHJlcXVlc3Qgb2Ygc3R5bGUuXG4vL1xuLy8gY2Fub25pY2FsUmVxdWVzdCA9XG4vLyAgPEhUVFBNZXRob2Q+XFxuXG4vLyAgPENhbm9uaWNhbFVSST5cXG5cbi8vICA8Q2Fub25pY2FsUXVlcnlTdHJpbmc+XFxuXG4vLyAgPENhbm9uaWNhbEhlYWRlcnM+XFxuXG4vLyAgPFNpZ25lZEhlYWRlcnM+XFxuXG4vLyAgPEhhc2hlZFBheWxvYWQ+XG4vL1xuZnVuY3Rpb24gZ2V0Q2Fub25pY2FsUmVxdWVzdChcbiAgbWV0aG9kOiBzdHJpbmcsXG4gIHBhdGg6IHN0cmluZyxcbiAgaGVhZGVyczogUmVxdWVzdEhlYWRlcnMsXG4gIHNpZ25lZEhlYWRlcnM6IHN0cmluZ1tdLFxuICBoYXNoZWRQYXlsb2FkOiBzdHJpbmcsXG4pOiBJQ2Fub25pY2FsUmVxdWVzdCB7XG4gIGlmICghaXNTdHJpbmcobWV0aG9kKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21ldGhvZCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgfVxuICBpZiAoIWlzU3RyaW5nKHBhdGgpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncGF0aCBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgfVxuICBpZiAoIWlzT2JqZWN0KGhlYWRlcnMpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaGVhZGVycyBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgfVxuICBpZiAoIUFycmF5LmlzQXJyYXkoc2lnbmVkSGVhZGVycykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzaWduZWRIZWFkZXJzIHNob3VsZCBiZSBvZiB0eXBlIFwiYXJyYXlcIicpXG4gIH1cbiAgaWYgKCFpc1N0cmluZyhoYXNoZWRQYXlsb2FkKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2hhc2hlZFBheWxvYWQgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gIH1cblxuICBjb25zdCBoZWFkZXJzQXJyYXkgPSBzaWduZWRIZWFkZXJzLnJlZHVjZSgoYWNjLCBpKSA9PiB7XG4gICAgLy8gVHJpbSBzcGFjZXMgZnJvbSB0aGUgdmFsdWUgKHJlcXVpcmVkIGJ5IFY0IHNwZWMpXG4gICAgY29uc3QgdmFsID0gYCR7aGVhZGVyc1tpXX1gLnJlcGxhY2UoLyArL2csICcgJylcbiAgICBhY2MucHVzaChgJHtpLnRvTG93ZXJDYXNlKCl9OiR7dmFsfWApXG4gICAgcmV0dXJuIGFjY1xuICB9LCBbXSBhcyBzdHJpbmdbXSlcblxuICBjb25zdCByZXF1ZXN0UmVzb3VyY2UgPSBwYXRoLnNwbGl0KCc/JylbMF1cbiAgbGV0IHJlcXVlc3RRdWVyeSA9IHBhdGguc3BsaXQoJz8nKVsxXVxuICBpZiAoIXJlcXVlc3RRdWVyeSkge1xuICAgIHJlcXVlc3RRdWVyeSA9ICcnXG4gIH1cblxuICBpZiAocmVxdWVzdFF1ZXJ5KSB7XG4gICAgcmVxdWVzdFF1ZXJ5ID0gcmVxdWVzdFF1ZXJ5XG4gICAgICAuc3BsaXQoJyYnKVxuICAgICAgLnNvcnQoKVxuICAgICAgLm1hcCgoZWxlbWVudCkgPT4gKCFlbGVtZW50LmluY2x1ZGVzKCc9JykgPyBlbGVtZW50ICsgJz0nIDogZWxlbWVudCkpXG4gICAgICAuam9pbignJicpXG4gIH1cblxuICByZXR1cm4gW1xuICAgIG1ldGhvZC50b1VwcGVyQ2FzZSgpLFxuICAgIHJlcXVlc3RSZXNvdXJjZSxcbiAgICByZXF1ZXN0UXVlcnksXG4gICAgaGVhZGVyc0FycmF5LmpvaW4oJ1xcbicpICsgJ1xcbicsXG4gICAgc2lnbmVkSGVhZGVycy5qb2luKCc7JykudG9Mb3dlckNhc2UoKSxcbiAgICBoYXNoZWRQYXlsb2FkLFxuICBdLmpvaW4oJ1xcbicpXG59XG5cbi8vIGdlbmVyYXRlIGEgY3JlZGVudGlhbCBzdHJpbmdcbmZ1bmN0aW9uIGdldENyZWRlbnRpYWwoYWNjZXNzS2V5OiBzdHJpbmcsIHJlZ2lvbjogc3RyaW5nLCByZXF1ZXN0RGF0ZT86IERhdGUsIHNlcnZpY2VOYW1lID0gJ3MzJykge1xuICBpZiAoIWlzU3RyaW5nKGFjY2Vzc0tleSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdhY2Nlc3NLZXkgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gIH1cbiAgaWYgKCFpc1N0cmluZyhyZWdpb24pKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVnaW9uIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICB9XG4gIGlmICghaXNPYmplY3QocmVxdWVzdERhdGUpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVxdWVzdERhdGUgc2hvdWxkIGJlIG9mIHR5cGUgXCJvYmplY3RcIicpXG4gIH1cbiAgcmV0dXJuIGAke2FjY2Vzc0tleX0vJHtnZXRTY29wZShyZWdpb24sIHJlcXVlc3REYXRlLCBzZXJ2aWNlTmFtZSl9YFxufVxuXG4vLyBSZXR1cm5zIHNpZ25lZCBoZWFkZXJzIGFycmF5IC0gYWxwaGFiZXRpY2FsbHkgc29ydGVkXG5mdW5jdGlvbiBnZXRTaWduZWRIZWFkZXJzKGhlYWRlcnM6IFJlcXVlc3RIZWFkZXJzKTogc3RyaW5nW10ge1xuICBpZiAoIWlzT2JqZWN0KGhlYWRlcnMpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVxdWVzdCBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgfVxuICAvLyBFeGNlcnB0cyBmcm9tIEBsc2VnYWwgLSBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1zZGstanMvaXNzdWVzLzY1OSNpc3N1ZWNvbW1lbnQtMTIwNDc3MjU4XG4gIC8vXG4gIC8vICBVc2VyLUFnZW50OlxuICAvL1xuICAvLyAgICAgIFRoaXMgaXMgaWdub3JlZCBmcm9tIHNpZ25pbmcgYmVjYXVzZSBzaWduaW5nIHRoaXMgY2F1c2VzIHByb2JsZW1zIHdpdGggZ2VuZXJhdGluZyBwcmUtc2lnbmVkIFVSTHNcbiAgLy8gICAgICAodGhhdCBhcmUgZXhlY3V0ZWQgYnkgb3RoZXIgYWdlbnRzKSBvciB3aGVuIGN1c3RvbWVycyBwYXNzIHJlcXVlc3RzIHRocm91Z2ggcHJveGllcywgd2hpY2ggbWF5XG4gIC8vICAgICAgbW9kaWZ5IHRoZSB1c2VyLWFnZW50LlxuICAvL1xuICAvLyAgQ29udGVudC1MZW5ndGg6XG4gIC8vXG4gIC8vICAgICAgVGhpcyBpcyBpZ25vcmVkIGZyb20gc2lnbmluZyBiZWNhdXNlIGdlbmVyYXRpbmcgYSBwcmUtc2lnbmVkIFVSTCBzaG91bGQgbm90IHByb3ZpZGUgYSBjb250ZW50LWxlbmd0aFxuICAvLyAgICAgIGNvbnN0cmFpbnQsIHNwZWNpZmljYWxseSB3aGVuIHZlbmRpbmcgYSBTMyBwcmUtc2lnbmVkIFBVVCBVUkwuIFRoZSBjb3JvbGxhcnkgdG8gdGhpcyBpcyB0aGF0IHdoZW5cbiAgLy8gICAgICBzZW5kaW5nIHJlZ3VsYXIgcmVxdWVzdHMgKG5vbi1wcmUtc2lnbmVkKSwgdGhlIHNpZ25hdHVyZSBjb250YWlucyBhIGNoZWNrc3VtIG9mIHRoZSBib2R5LCB3aGljaFxuICAvLyAgICAgIGltcGxpY2l0bHkgdmFsaWRhdGVzIHRoZSBwYXlsb2FkIGxlbmd0aCAoc2luY2UgY2hhbmdpbmcgdGhlIG51bWJlciBvZiBieXRlcyB3b3VsZCBjaGFuZ2UgdGhlIGNoZWNrc3VtKVxuICAvLyAgICAgIGFuZCB0aGVyZWZvcmUgdGhpcyBoZWFkZXIgaXMgbm90IHZhbHVhYmxlIGluIHRoZSBzaWduYXR1cmUuXG4gIC8vXG4gIC8vICBDb250ZW50LVR5cGU6XG4gIC8vXG4gIC8vICAgICAgU2lnbmluZyB0aGlzIGhlYWRlciBjYXVzZXMgcXVpdGUgYSBudW1iZXIgb2YgcHJvYmxlbXMgaW4gYnJvd3NlciBlbnZpcm9ubWVudHMsIHdoZXJlIGJyb3dzZXJzXG4gIC8vICAgICAgbGlrZSB0byBtb2RpZnkgYW5kIG5vcm1hbGl6ZSB0aGUgY29udGVudC10eXBlIGhlYWRlciBpbiBkaWZmZXJlbnQgd2F5cy4gVGhlcmUgaXMgbW9yZSBpbmZvcm1hdGlvblxuICAvLyAgICAgIG9uIHRoaXMgaW4gaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3Mtc2RrLWpzL2lzc3Vlcy8yNDQuIEF2b2lkaW5nIHRoaXMgZmllbGQgc2ltcGxpZmllcyBsb2dpY1xuICAvLyAgICAgIGFuZCByZWR1Y2VzIHRoZSBwb3NzaWJpbGl0eSBvZiBmdXR1cmUgYnVnc1xuICAvL1xuICAvLyAgQXV0aG9yaXphdGlvbjpcbiAgLy9cbiAgLy8gICAgICBJcyBza2lwcGVkIGZvciBvYnZpb3VzIHJlYXNvbnNcblxuICBjb25zdCBpZ25vcmVkSGVhZGVycyA9IFsnYXV0aG9yaXphdGlvbicsICdjb250ZW50LWxlbmd0aCcsICdjb250ZW50LXR5cGUnLCAndXNlci1hZ2VudCddXG4gIHJldHVybiBPYmplY3Qua2V5cyhoZWFkZXJzKVxuICAgIC5maWx0ZXIoKGhlYWRlcikgPT4gIWlnbm9yZWRIZWFkZXJzLmluY2x1ZGVzKGhlYWRlcikpXG4gICAgLnNvcnQoKVxufVxuXG4vLyByZXR1cm5zIHRoZSBrZXkgdXNlZCBmb3IgY2FsY3VsYXRpbmcgc2lnbmF0dXJlXG5mdW5jdGlvbiBnZXRTaWduaW5nS2V5KGRhdGU6IERhdGUsIHJlZ2lvbjogc3RyaW5nLCBzZWNyZXRLZXk6IHN0cmluZywgc2VydmljZU5hbWUgPSAnczMnKSB7XG4gIGlmICghaXNPYmplY3QoZGF0ZSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRlIHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICB9XG4gIGlmICghaXNTdHJpbmcocmVnaW9uKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3JlZ2lvbiBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgfVxuICBpZiAoIWlzU3RyaW5nKHNlY3JldEtleSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzZWNyZXRLZXkgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gIH1cbiAgY29uc3QgZGF0ZUxpbmUgPSBtYWtlRGF0ZVNob3J0KGRhdGUpXG4gIGNvbnN0IGhtYWMxID0gY3J5cHRvXG4gICAgICAuY3JlYXRlSG1hYygnc2hhMjU2JywgJ0FXUzQnICsgc2VjcmV0S2V5KVxuICAgICAgLnVwZGF0ZShkYXRlTGluZSlcbiAgICAgIC5kaWdlc3QoKSxcbiAgICBobWFjMiA9IGNyeXB0by5jcmVhdGVIbWFjKCdzaGEyNTYnLCBobWFjMSkudXBkYXRlKHJlZ2lvbikuZGlnZXN0KCksXG4gICAgaG1hYzMgPSBjcnlwdG8uY3JlYXRlSG1hYygnc2hhMjU2JywgaG1hYzIpLnVwZGF0ZShzZXJ2aWNlTmFtZSkuZGlnZXN0KClcbiAgcmV0dXJuIGNyeXB0by5jcmVhdGVIbWFjKCdzaGEyNTYnLCBobWFjMykudXBkYXRlKCdhd3M0X3JlcXVlc3QnKS5kaWdlc3QoKVxufVxuXG4vLyByZXR1cm5zIHRoZSBzdHJpbmcgdGhhdCBuZWVkcyB0byBiZSBzaWduZWRcbmZ1bmN0aW9uIGdldFN0cmluZ1RvU2lnbihjYW5vbmljYWxSZXF1ZXN0OiBJQ2Fub25pY2FsUmVxdWVzdCwgcmVxdWVzdERhdGU6IERhdGUsIHJlZ2lvbjogc3RyaW5nLCBzZXJ2aWNlTmFtZSA9ICdzMycpIHtcbiAgaWYgKCFpc1N0cmluZyhjYW5vbmljYWxSZXF1ZXN0KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2Nhbm9uaWNhbFJlcXVlc3Qgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gIH1cbiAgaWYgKCFpc09iamVjdChyZXF1ZXN0RGF0ZSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXF1ZXN0RGF0ZSBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgfVxuICBpZiAoIWlzU3RyaW5nKHJlZ2lvbikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWdpb24gc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gIH1cbiAgY29uc3QgaGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoY2Fub25pY2FsUmVxdWVzdCkuZGlnZXN0KCdoZXgnKVxuICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHJlZ2lvbiwgcmVxdWVzdERhdGUsIHNlcnZpY2VOYW1lKVxuICBjb25zdCBzdHJpbmdUb1NpZ24gPSBbc2lnblY0QWxnb3JpdGhtLCBtYWtlRGF0ZUxvbmcocmVxdWVzdERhdGUpLCBzY29wZSwgaGFzaF1cblxuICByZXR1cm4gc3RyaW5nVG9TaWduLmpvaW4oJ1xcbicpXG59XG5cbi8vIGNhbGN1bGF0ZSB0aGUgc2lnbmF0dXJlIG9mIHRoZSBQT1NUIHBvbGljeVxuZXhwb3J0IGZ1bmN0aW9uIHBvc3RQcmVzaWduU2lnbmF0dXJlVjQocmVnaW9uOiBzdHJpbmcsIGRhdGU6IERhdGUsIHNlY3JldEtleTogc3RyaW5nLCBwb2xpY3lCYXNlNjQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghaXNTdHJpbmcocmVnaW9uKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3JlZ2lvbiBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgfVxuICBpZiAoIWlzT2JqZWN0KGRhdGUpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF0ZSBzaG91bGQgYmUgb2YgdHlwZSBcIm9iamVjdFwiJylcbiAgfVxuICBpZiAoIWlzU3RyaW5nKHNlY3JldEtleSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzZWNyZXRLZXkgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gIH1cbiAgaWYgKCFpc1N0cmluZyhwb2xpY3lCYXNlNjQpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncG9saWN5QmFzZTY0IHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICB9XG4gIGNvbnN0IHNpZ25pbmdLZXkgPSBnZXRTaWduaW5nS2V5KGRhdGUsIHJlZ2lvbiwgc2VjcmV0S2V5KVxuICByZXR1cm4gY3J5cHRvLmNyZWF0ZUhtYWMoJ3NoYTI1NicsIHNpZ25pbmdLZXkpLnVwZGF0ZShwb2xpY3lCYXNlNjQpLmRpZ2VzdCgnaGV4JykudG9Mb3dlckNhc2UoKVxufVxuXG4vLyBSZXR1cm5zIHRoZSBhdXRob3JpemF0aW9uIGhlYWRlclxuZXhwb3J0IGZ1bmN0aW9uIHNpZ25WNChcbiAgcmVxdWVzdDogSVJlcXVlc3QsXG4gIGFjY2Vzc0tleTogc3RyaW5nLFxuICBzZWNyZXRLZXk6IHN0cmluZyxcbiAgcmVnaW9uOiBzdHJpbmcsXG4gIHJlcXVlc3REYXRlOiBEYXRlLFxuICBzaGEyNTZzdW06IHN0cmluZyxcbiAgc2VydmljZU5hbWUgPSAnczMnLFxuKSB7XG4gIGlmICghaXNPYmplY3QocmVxdWVzdCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXF1ZXN0IHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICB9XG4gIGlmICghaXNTdHJpbmcoYWNjZXNzS2V5KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FjY2Vzc0tleSBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgfVxuICBpZiAoIWlzU3RyaW5nKHNlY3JldEtleSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzZWNyZXRLZXkgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gIH1cbiAgaWYgKCFpc1N0cmluZyhyZWdpb24pKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVnaW9uIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICB9XG5cbiAgaWYgKCFhY2Nlc3NLZXkpIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLkFjY2Vzc0tleVJlcXVpcmVkRXJyb3IoJ2FjY2Vzc0tleSBpcyByZXF1aXJlZCBmb3Igc2lnbmluZycpXG4gIH1cbiAgaWYgKCFzZWNyZXRLZXkpIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLlNlY3JldEtleVJlcXVpcmVkRXJyb3IoJ3NlY3JldEtleSBpcyByZXF1aXJlZCBmb3Igc2lnbmluZycpXG4gIH1cblxuICBjb25zdCBzaWduZWRIZWFkZXJzID0gZ2V0U2lnbmVkSGVhZGVycyhyZXF1ZXN0LmhlYWRlcnMpXG4gIGNvbnN0IGNhbm9uaWNhbFJlcXVlc3QgPSBnZXRDYW5vbmljYWxSZXF1ZXN0KHJlcXVlc3QubWV0aG9kLCByZXF1ZXN0LnBhdGgsIHJlcXVlc3QuaGVhZGVycywgc2lnbmVkSGVhZGVycywgc2hhMjU2c3VtKVxuICBjb25zdCBzZXJ2aWNlSWRlbnRpZmllciA9IHNlcnZpY2VOYW1lIHx8ICdzMydcbiAgY29uc3Qgc3RyaW5nVG9TaWduID0gZ2V0U3RyaW5nVG9TaWduKGNhbm9uaWNhbFJlcXVlc3QsIHJlcXVlc3REYXRlLCByZWdpb24sIHNlcnZpY2VJZGVudGlmaWVyKVxuICBjb25zdCBzaWduaW5nS2V5ID0gZ2V0U2lnbmluZ0tleShyZXF1ZXN0RGF0ZSwgcmVnaW9uLCBzZWNyZXRLZXksIHNlcnZpY2VJZGVudGlmaWVyKVxuICBjb25zdCBjcmVkZW50aWFsID0gZ2V0Q3JlZGVudGlhbChhY2Nlc3NLZXksIHJlZ2lvbiwgcmVxdWVzdERhdGUsIHNlcnZpY2VJZGVudGlmaWVyKVxuICBjb25zdCBzaWduYXR1cmUgPSBjcnlwdG8uY3JlYXRlSG1hYygnc2hhMjU2Jywgc2lnbmluZ0tleSkudXBkYXRlKHN0cmluZ1RvU2lnbikuZGlnZXN0KCdoZXgnKS50b0xvd2VyQ2FzZSgpXG5cbiAgcmV0dXJuIGAke3NpZ25WNEFsZ29yaXRobX0gQ3JlZGVudGlhbD0ke2NyZWRlbnRpYWx9LCBTaWduZWRIZWFkZXJzPSR7c2lnbmVkSGVhZGVyc1xuICAgIC5qb2luKCc7JylcbiAgICAudG9Mb3dlckNhc2UoKX0sIFNpZ25hdHVyZT0ke3NpZ25hdHVyZX1gXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzaWduVjRCeVNlcnZpY2VOYW1lKFxuICByZXF1ZXN0OiBJUmVxdWVzdCxcbiAgYWNjZXNzS2V5OiBzdHJpbmcsXG4gIHNlY3JldEtleTogc3RyaW5nLFxuICByZWdpb246IHN0cmluZyxcbiAgcmVxdWVzdERhdGU6IERhdGUsXG4gIGNvbnRlbnRTaGEyNTY6IHN0cmluZyxcbiAgc2VydmljZU5hbWUgPSAnczMnLFxuKTogc3RyaW5nIHtcbiAgcmV0dXJuIHNpZ25WNChyZXF1ZXN0LCBhY2Nlc3NLZXksIHNlY3JldEtleSwgcmVnaW9uLCByZXF1ZXN0RGF0ZSwgY29udGVudFNoYTI1Niwgc2VydmljZU5hbWUpXG59XG5cbi8vIHJldHVybnMgYSBwcmVzaWduZWQgVVJMIHN0cmluZ1xuZXhwb3J0IGZ1bmN0aW9uIHByZXNpZ25TaWduYXR1cmVWNChcbiAgcmVxdWVzdDogSVJlcXVlc3QsXG4gIGFjY2Vzc0tleTogc3RyaW5nLFxuICBzZWNyZXRLZXk6IHN0cmluZyxcbiAgc2Vzc2lvblRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIHJlZ2lvbjogc3RyaW5nLFxuICByZXF1ZXN0RGF0ZTogRGF0ZSxcbiAgZXhwaXJlczogbnVtYmVyLFxuKSB7XG4gIGlmICghaXNPYmplY3QocmVxdWVzdCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXF1ZXN0IHNob3VsZCBiZSBvZiB0eXBlIFwib2JqZWN0XCInKVxuICB9XG4gIGlmICghaXNTdHJpbmcoYWNjZXNzS2V5KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FjY2Vzc0tleSBzaG91bGQgYmUgb2YgdHlwZSBcInN0cmluZ1wiJylcbiAgfVxuICBpZiAoIWlzU3RyaW5nKHNlY3JldEtleSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdzZWNyZXRLZXkgc2hvdWxkIGJlIG9mIHR5cGUgXCJzdHJpbmdcIicpXG4gIH1cbiAgaWYgKCFpc1N0cmluZyhyZWdpb24pKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVnaW9uIHNob3VsZCBiZSBvZiB0eXBlIFwic3RyaW5nXCInKVxuICB9XG5cbiAgaWYgKCFhY2Nlc3NLZXkpIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLkFjY2Vzc0tleVJlcXVpcmVkRXJyb3IoJ2FjY2Vzc0tleSBpcyByZXF1aXJlZCBmb3IgcHJlc2lnbmluZycpXG4gIH1cbiAgaWYgKCFzZWNyZXRLZXkpIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLlNlY3JldEtleVJlcXVpcmVkRXJyb3IoJ3NlY3JldEtleSBpcyByZXF1aXJlZCBmb3IgcHJlc2lnbmluZycpXG4gIH1cblxuICBpZiAoIWlzTnVtYmVyKGV4cGlyZXMpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZXhwaXJlcyBzaG91bGQgYmUgb2YgdHlwZSBcIm51bWJlclwiJylcbiAgfVxuICBpZiAoZXhwaXJlcyA8IDEpIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLkV4cGlyZXNQYXJhbUVycm9yKCdleHBpcmVzIHBhcmFtIGNhbm5vdCBiZSBsZXNzIHRoYW4gMSBzZWNvbmRzJylcbiAgfVxuICBpZiAoZXhwaXJlcyA+IDYwNDgwMCkge1xuICAgIHRocm93IG5ldyBlcnJvcnMuRXhwaXJlc1BhcmFtRXJyb3IoJ2V4cGlyZXMgcGFyYW0gY2Fubm90IGJlIGdyZWF0ZXIgdGhhbiA3IGRheXMnKVxuICB9XG5cbiAgY29uc3QgaXNvODYwMURhdGUgPSBtYWtlRGF0ZUxvbmcocmVxdWVzdERhdGUpXG4gIGNvbnN0IHNpZ25lZEhlYWRlcnMgPSBnZXRTaWduZWRIZWFkZXJzKHJlcXVlc3QuaGVhZGVycylcbiAgY29uc3QgY3JlZGVudGlhbCA9IGdldENyZWRlbnRpYWwoYWNjZXNzS2V5LCByZWdpb24sIHJlcXVlc3REYXRlKVxuICBjb25zdCBoYXNoZWRQYXlsb2FkID0gJ1VOU0lHTkVELVBBWUxPQUQnXG5cbiAgY29uc3QgcmVxdWVzdFF1ZXJ5OiBzdHJpbmdbXSA9IFtdXG4gIHJlcXVlc3RRdWVyeS5wdXNoKGBYLUFtei1BbGdvcml0aG09JHtzaWduVjRBbGdvcml0aG19YClcbiAgcmVxdWVzdFF1ZXJ5LnB1c2goYFgtQW16LUNyZWRlbnRpYWw9JHt1cmlFc2NhcGUoY3JlZGVudGlhbCl9YClcbiAgcmVxdWVzdFF1ZXJ5LnB1c2goYFgtQW16LURhdGU9JHtpc284NjAxRGF0ZX1gKVxuICByZXF1ZXN0UXVlcnkucHVzaChgWC1BbXotRXhwaXJlcz0ke2V4cGlyZXN9YClcbiAgcmVxdWVzdFF1ZXJ5LnB1c2goYFgtQW16LVNpZ25lZEhlYWRlcnM9JHt1cmlFc2NhcGUoc2lnbmVkSGVhZGVycy5qb2luKCc7JykudG9Mb3dlckNhc2UoKSl9YClcbiAgaWYgKHNlc3Npb25Ub2tlbikge1xuICAgIHJlcXVlc3RRdWVyeS5wdXNoKGBYLUFtei1TZWN1cml0eS1Ub2tlbj0ke3VyaUVzY2FwZShzZXNzaW9uVG9rZW4pfWApXG4gIH1cblxuICBjb25zdCByZXNvdXJjZSA9IHJlcXVlc3QucGF0aC5zcGxpdCgnPycpWzBdXG4gIGxldCBxdWVyeSA9IHJlcXVlc3QucGF0aC5zcGxpdCgnPycpWzFdXG4gIGlmIChxdWVyeSkge1xuICAgIHF1ZXJ5ID0gcXVlcnkgKyAnJicgKyByZXF1ZXN0UXVlcnkuam9pbignJicpXG4gIH0gZWxzZSB7XG4gICAgcXVlcnkgPSByZXF1ZXN0UXVlcnkuam9pbignJicpXG4gIH1cblxuICBjb25zdCBwYXRoID0gcmVzb3VyY2UgKyAnPycgKyBxdWVyeVxuXG4gIGNvbnN0IGNhbm9uaWNhbFJlcXVlc3QgPSBnZXRDYW5vbmljYWxSZXF1ZXN0KHJlcXVlc3QubWV0aG9kLCBwYXRoLCByZXF1ZXN0LmhlYWRlcnMsIHNpZ25lZEhlYWRlcnMsIGhhc2hlZFBheWxvYWQpXG5cbiAgY29uc3Qgc3RyaW5nVG9TaWduID0gZ2V0U3RyaW5nVG9TaWduKGNhbm9uaWNhbFJlcXVlc3QsIHJlcXVlc3REYXRlLCByZWdpb24pXG4gIGNvbnN0IHNpZ25pbmdLZXkgPSBnZXRTaWduaW5nS2V5KHJlcXVlc3REYXRlLCByZWdpb24sIHNlY3JldEtleSlcbiAgY29uc3Qgc2lnbmF0dXJlID0gY3J5cHRvLmNyZWF0ZUhtYWMoJ3NoYTI1NicsIHNpZ25pbmdLZXkpLnVwZGF0ZShzdHJpbmdUb1NpZ24pLmRpZ2VzdCgnaGV4JykudG9Mb3dlckNhc2UoKVxuICByZXR1cm4gcmVxdWVzdC5wcm90b2NvbCArICcvLycgKyByZXF1ZXN0LmhlYWRlcnMuaG9zdCArIHBhdGggKyBgJlgtQW16LVNpZ25hdHVyZT0ke3NpZ25hdHVyZX1gXG59XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxPQUFPLEtBQUtBLE1BQU07QUFFbEIsT0FBTyxLQUFLQyxNQUFNLE1BQU0sY0FBYTtBQUNyQyxTQUFTQyxRQUFRLEVBQUVDLFFBQVEsRUFBRUMsUUFBUSxFQUFFQyxRQUFRLEVBQUVDLFlBQVksRUFBRUMsYUFBYSxFQUFFQyxTQUFTLFFBQVEsdUJBQXNCO0FBR3JILE1BQU1DLGVBQWUsR0FBRyxrQkFBa0I7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsbUJBQW1CQSxDQUMxQkMsTUFBYyxFQUNkQyxJQUFZLEVBQ1pDLE9BQXVCLEVBQ3ZCQyxhQUF1QixFQUN2QkMsYUFBcUIsRUFDRjtFQUNuQixJQUFJLENBQUNWLFFBQVEsQ0FBQ00sTUFBTSxDQUFDLEVBQUU7SUFDckIsTUFBTSxJQUFJ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